package com.wisecoach.gatewayplus.event;

import com.wisecoach.util.Assert;
import com.wisecoach.util.StringUtils;
import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import org.hyperledger.fabric.client.Gateway;
import org.hyperledger.fabric.client.Network;
import org.hyperledger.fabric.client.identity.Identities;
import org.hyperledger.fabric.client.identity.Signer;
import org.hyperledger.fabric.client.identity.Signers;
import org.hyperledger.fabric.client.identity.X509Identity;

import java.io.FileReader;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * {@code @author:} wisecoach
 * {@code @date:} 2023/6/15 下午4:07
 * {@code @version:} 1.0.0
 */


public class DefaultFilteredBlockSourceFactory implements FilteredBlockSourceFactory {

    private final ExecutorService executorService = Executors.newCachedThreadPool();

    @Override
    public FilteredBlockSource getSource(FilteredBlockSourceInfo info) {
        try {
            FileReader certReader = new FileReader(info.getSignerCert());
            X509Certificate cert = Identities.readX509Certificate(certReader);
            X509Identity identity = new X509Identity(info.getMspId(), cert);

            FileReader secretReader = new FileReader(info.getSignerSecret());
            PrivateKey privateKey = Identities.readPrivateKey(secretReader);
            Signer signer = Signers.newPrivateKeySigner(privateKey);


            String endpoint = info.getEndpoint();
            Assert.hasLength(endpoint, "endpoint不可为空");
            NettyChannelBuilder builder = NettyChannelBuilder.forTarget(endpoint);
            // 设置tls环境
            if (info.getTlsCert() != null) {
                try (FileReader tlsReader = new FileReader(info.getTlsCert())) {
                    X509Certificate tlsCert = Identities.readX509Certificate(tlsReader);
                    builder.sslContext(GrpcSslContexts.forClient().trustManager(tlsCert).build());
                }
            }
            // 设置authority
            if (StringUtils.hasLength(info.getAuthority())) {
                builder.overrideAuthority(info.getAuthority());
            }
            ManagedChannel channel = builder.build();

            String channelName;
            Network network;
            try (Gateway gateway = Gateway.newInstance().identity(identity).signer(signer).connection(channel).connect()) {
                channelName = info.getChannelName();
                network = gateway.getNetwork(channelName);
            }
            return new DefaultFilteredBlockSource(channelName, network, executorService);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
